<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Canvas 练习</title>
</head>
<style>
    .origin-img-container {
        width: 500px;
        height: 500px;
        border: slategrey 1px solid;
        margin-right: 100px;
        overflow: hidden;
        position: relative;
        background-color: darkgrey;
    }

    .prieview-img-container {
        width: 100px;
        height: 100px;
        border: slategrey 1px solid;
    }

    .hide-item {
        display: none;
    }

    .img {
        position: absolute;
        top: 0;
        left: 0;
        z-index: 1;
    }

    .container {
        display: flex;
        justify-content: center;
        align-items: center;
    }

    .cut-container {
        width: 100px;
        height: 100px;
        border: white 2px solid;
        box-shadow: 1px 1px 2px 2px black;
        position: absolute;
        left: 100px;
        top: 100px;
        z-index: 10;
    }

    .cub {
        width: 10px;
        height: 10px;
        background-color: white;
        position: absolute;
        box-shadow: 1px 1px 2px 2px black;
    }

    .cub:hover {
        transform: scale(1.2, 1.2);
    }

    .cub1 {
        top: 5px;
        left: 5px;
        z-index: 11;
    }

    .cub2 {
        top: 95px;
        left: 95px;
        z-index: 11;
    }
</style>

<body>
    <input type="file" name="请选择文件" id="fileInputId">
    <div class="container">
        <div class="origin-img-container" id="container">
            <img src="" class="hide-item img" style="cursor:move" id="targetImg" />
            <div class="cub cub1" id="cub1"></div>
            <div class="cub cub2" id="cub2"></div>
            <div class="cut-container" id="cutContainer"></div>
        </div>
        <div class="prieview-img-container" id="imgContainer">
            <!-- 预览的图片位置 -->
            <img src="" alt="" id="priviewImg">
        </div>
    </div>
</body>
<script>
    var canvas = document.createElement('canvas')
    var ctx = canvas.getContext('2d')
    var fi = document.getElementById('fileInputId')
    var targetImg = document.getElementById('targetImg')
    var cub1 = document.getElementById('cub1')
    var cub2 = document.getElementById('cub2')
    var container = document.getElementById('container')
    var cutContainer = document.getElementById('cutContainer')
    var priviewImg = document.getElementById('priviewImg')
    var imgContainer = document.getElementById('imgContainer')
    var btn = document.getElementById('btn')

    var mousedownX = 0;
    var mousedownY = 0;
    var support =
        "onwheel" in document.createElement("div") ?
        "wheel" :
        document.onmousewheel !== undefined ?
        "mousewheel" :
        "DOMMouseScroll";
    var originImgUrl;
    var mul = 2
    var min = 0.1
    var scaleStep = 2
    var rateBase = 10000
    var scaleDelt = 10000
    var scaleRate = 1;
    var trueImgX = 0;
    var trueImgY = 0;
    const scaleFun = (e) => {
      e.preventDefault();
      console.log(e)
      if(e.deltaY > 0 && scaleDelt < rateBase * mul  ){
        scaleDelt += e.deltaY*scaleStep
      }else if(e.deltaY < 0 && scaleDelt > rateBase * min){
        scaleDelt += e.deltaY*scaleStep
      }else{
        return
      }
      scaleRate = scaleDelt/rateBase
      targetImg.style.transform = `scale(${scaleRate},${scaleRate})`
    }
    window.addEventListener(this.support,scaleFun,{ passive: false });
    // 1 取到图像信息
    fi.onchange = () => {
        const file = fi.files[0]
        if (!file) return
        if (!['image/jpeg', 'image/jpg', 'image/png'].includes(file.type)) {
            alert('文件不支持')
            fi.value = ''
            return
        }
        originImgUrl = window.URL.createObjectURL(file)
        var reader = new FileReader();
        reader.readAsDataURL(file)
        reader.onloadend = (e) => {
            targetImg.src = e.target.result
            showItem()
        }
    }
    fi.onloadeddata = (f) => {
      console.log('FFFF: ',f)
    }

    // 使元素移动的方法
    var itemMove = (ele, baseEle, moveCb, upCb) => {
        console.log(ele)
        let draging = false
        if (!ele) return
            // 对图片的操作---start
        ele.addEventListener('mousedown', (e) => {
            e.preventDefault()
            draging = true
                // 第二次按住鼠标时，坐标与mousemove的一致，会导致图片回到左上角
            mousedownX = e.clientX - ele.offsetLeft
            mousedownY = e.clientY - ele.offsetTop
        })
        ele.addEventListener('mouseup', (e) => {
            draging = false
            if (upCb) upCb(e)
        })
        const moveEle = baseEle || ele
        moveEle.addEventListener('mousemove', (e) => {
            if (draging) {
                ele.style.left = e.clientX - mousedownX + 'px'
                ele.style.top = e.clientY - mousedownY + 'px'
                if (moveCb) {
                    moveCb(e)
                }
            }
        })
    }

    // 图像移动
    itemMove(targetImg)

    // 让截图框基于控制点生成
    var resetCutContainer = () => {
        const cub1X = cub1.offsetLeft
        const cub1Y = cub1.offsetTop

        const cub2X = cub2.offsetLeft
        const cub2Y = cub2.offsetTop

        cutContainer.style.left = cub1X + 3 + 'px'
        cutContainer.style.top = cub1Y + 3 + 'px'

        cutContainer.style.width = cub2X - cub1X - 1 + 'px'
        cutContainer.style.height = cub2Y - cub1Y - 1 + 'px'

    }

    // 要以大容器作为mousemove监听
    const cubMove = (e) => {
        // 让截图框基于控制点生成
        resetCutContainer()
    }
    const getBase64ByImageData = (content, width, height) => {
            let nCanvas = document.createElement('canvas')
            let nCtx = nCanvas.getContext('2d')
            nCanvas.width = width
            nCanvas.height = height
            nCtx.putImageData(content, 0, 0)
            return nCanvas.toDataURL('image/png')
        }
    const getTrueAix = () => {
      // 获取图片放大后的位置
      const x1 = targetImg.offsetLeft
      const y1 = targetImg.offsetTop
      trueImgX = x1 + targetImg.offsetWidth/2 * (1 - scaleRate)
      trueImgY = y1 + targetImg.offsetHeight/2 * (1 - scaleRate)
      console.log('trueImgX: ',trueImgX,'trueImgY: ',trueImgY)
    }
    const getCutPic = () => {
        const image = new Image()
        image.onload = () => {
            //  获取原图高度和宽度
            const height = image.height
            const width = image.width
            canvas.height = height
            canvas.width = width
            ctx.drawImage(image, 0, 0, width, height);

            getTrueAix()

            const offW = cub2.offsetLeft - cub1.offsetLeft
            const offH = cub2.offsetTop - cub1.offsetTop
            // 获取截图后的像素点阵
            // 是以图片的坐标为准的
            const offX = cub1.offsetLeft - trueImgX
            const offY = cub1.offsetTop - trueImgY
            const scaleRateReverse = 1 / scaleRate
            const cutImg = ctx.getImageData(offX * scaleRateReverse, offY * scaleRateReverse, offW* scaleRateReverse, offH* scaleRateReverse)
            const cutImage = getBase64ByImageData(cutImg, offW, offH)
            priviewImg.src = cutImage
        }
        image.src = originImgUrl
    }
    itemMove(cub1, container, cubMove, getCutPic)
    itemMove(cub2, container, cubMove, getCutPic)

    resetCutContainer()

    var hideItem = () => {
        targetImg.classList.add('hide-item')
    }

    var showItem = () => {
        targetImg.classList.remove('hide-item')
    }
    cutContainer.style.pointerEvents = 'none'
</script>

</html>
